package db

import (
	"bytes"
	"core/env"
	"core/graylog"
	"core/minio_client"
	"core/rds"
	"core/utils"
	"github.com/go-redis/redis"
	"github.com/minio/minio-go"
	"github.com/nfnt/resize"
	"image"
	"image/jpeg"
	"image/png"
	"strings"
	"time"
)

const (
	picRunLoopTime = time.Millisecond * 50
)

var picRunLoopBet int64 = 1   // 调节速度
var picRunLoopCount int64 = 1 // 循环总数

func makeResizePicKey() string {
	return "resize-list"
}

func RunResizePicLoop() {
	tick := time.NewTicker(picRunLoopTime)
	for {
		select {
		case <-tick.C:
			picRunLoopCount++
			resizePicOne()
		}
	}
}

func resizePicOne() {
	if picRunLoopCount%picRunLoopBet != 0 {
		return
	}
	var err error
	defer utils.CatchPanicAndErr("SaveOneToMysql", &err, graylog.M{"picRunLoopCount": picRunLoopCount, "picRunLoopBet": picRunLoopBet})
	client := rds.GetResizePicClient()
	key := makeResizePicKey()
	picName, err := client.RPop(key).Result()
	if err == redis.Nil {
		if picRunLoopBet < 128 {
			picRunLoopBet *= 2
		}
		err = nil
		utils.Info(picRunLoopCount, picRunLoopBet)
		return
	} else if err != nil {
		return
	}
	if picRunLoopCount > 0xffffffff {
		picRunLoopCount = 0
	}

	utils.SageGoAndCatchErr(func() error {
		return resizeImg(picName)
	})
	err = resizeImg(picName)
	graylog.Info("压缩图片成功", graylog.M{
		"pic-name": picName,
	})
	return
}

func resizeImg(picName string) (err error) {
	index := strings.LastIndex(picName, ".")
	ext := picName[index:]
	object, err := minio_client.Client.GetObject(PicBucket, picName, minio.GetObjectOptions{})
	if err != nil {
		utils.Error(err)
		return
	}
	var originalPic image.Image
	var contentType string
	switch ext {
	case ".png":
		originalPic, err = png.Decode(object)
		contentType = "image/png"
	case ".jpg", ".jpeg":
		originalPic, err = jpeg.Decode(object)
		contentType = "image/jpg"
	}
	if err != nil {
		utils.Error(err)
		return
	}

	newImg := resize.Resize(200, 0, originalPic, resize.NearestNeighbor)
	buf := bytes.NewBuffer(make([]byte, 0, 65536))
	switch ext {
	case ".png":
		err = png.Encode(buf, newImg)
	case ".jpg", ".jpeg":
		err = jpeg.Encode(buf, newImg, nil)
	}
	miniName := env.GetMinPicName(picName)
	utils.Info("miniName", miniName)
	_, err = minio_client.Client.PutObject(PicBucket, miniName, buf, -1, minio.PutObjectOptions{ContentType: contentType})
	if err != nil {
		utils.Error(err)
		return
	}

	return
}

//
func PushToResizePicList(picName string) (err error) {
	utils.Info("PushToResizePicList", picName)
	client := rds.GetResizePicClient()
	key := makeResizePicKey()
	err = client.LPush(key, picName).Err()
	if err != nil {
		utils.Error(err)
		return
	}
	return
}
